/**
 * API Service for AIChat吉PT userscript.
 * Handles API interactions with external services.
 */
import {
  updateChatContent,
  updateChatHeader,
} from "../components/UIComponents";
import { scrollToTop } from "../utils/domUtils";

// 添加完成标识的样式
const completedStyle = document.createElement("style");
completedStyle.textContent = `
  .response-completed {
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 18px auto 5px auto;
    padding: 8px 15px;
    background: linear-gradient(90deg, rgba(99, 230, 190, 0.2), rgba(77, 138, 240, 0.2));
    border-radius: 20px;
    color: #63e6be;
    font-size: 13px;
    max-width: 180px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    border: 1px solid rgba(99, 230, 190, 0.3);
    animation: fadeInUp 0.5s ease;
  }
  
  @keyframes fadeInUp {
    from { 
      opacity: 0;
      transform: translateY(10px);
    }
    to { 
      opacity: 1;
      transform: translateY(0);
    }
  }
  
  .completed-icon {
    width: 22px;
    height: 22px;
    background-color: #63e6be;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #222;
    margin-right: 8px;
    font-weight: bold;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  }
  
  .retry-button {
    margin-top: 10px;
    padding: 6px 12px;
    background-color: #4d8af0;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.2s ease;
  }
  
  .retry-button:hover {
    background-color: #3a75d8;
    transform: translateY(-1px);
  }

  /* 防止对话闪烁的样式 */
  .ai-content {
    min-height: 60px;
    transition: none !important;
  }
  
  .ai-response {
    transition: none !important;
  }
  
  /* AI思考过程样式 */
  .ai-reasoning {
    margin-top: 10px;
    margin-bottom: 10px;
    padding: 10px 15px;
    background-color: rgba(77, 138, 240, 0.1);
    border-left: 3px solid #4d8af0;
    border-radius: 0 8px 8px 0;
    font-size: 14px;
    color: #e0e0e0;
    position: relative;
    max-height: none;
    overflow-y: visible;
    transition: max-height 0.3s ease;
    line-height: 1.5;
  }
  
  .ai-reasoning-header {
    display: flex;
    align-items: center;
    margin-bottom: 8px;
    padding-bottom: 5px;
    border-bottom: 1px solid rgba(77, 138, 240, 0.2);
    font-weight: 500;
    color: #4d8af0;
  }
  
  .ai-reasoning-icon {
    margin-right: 6px;
    width: 16px;
    height: 16px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%234d8af0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z'%3E%3C/path%3E%3Cpolyline points='3.27 6.96 12 12.01 20.73 6.96'%3E%3C/polyline%3E%3Cline x1='12' y1='22.08' x2='12' y2='12'%3E%3C/line%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
  }
  
  .ai-reasoning-toggle {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 20px;
    height: 20px;
    cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%234d8af0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    transition: transform 0.3s ease;
    opacity: 0.7;
  }
  
  .ai-reasoning-toggle:hover {
    opacity: 1;
  }
  
  .ai-reasoning-toggle.collapsed {
    transform: rotate(180deg);
  }
  
  .ai-reasoning-content {
    white-space: pre-wrap;
    font-family: "JetBrains Mono", "Fira Code", monospace;
    font-size: 13px;
  }
  
  .ai-reasoning.collapsed {
    max-height: 40px;
    overflow: hidden;
    margin-bottom: 5px;
    opacity: 0.85;
  }
`;
document.head.appendChild(completedStyle);

/**
 * Generates a prompt for the chat model based on the type of chat and language
 * @param {Object} params - Parameters for generating the prompt
 * @param {number} params.chatType - The type of chat interaction
 * @param {string} params.languageType - The programming language type
 * @returns {string} - The generated prompt
 */
export function generatePrompt(params) {
  const { chatType, languageType } = params;
  let prompt = "";

  // Setup base system instructions for all prompts
  prompt += `你是代码领域的专家，以下是${languageType}代码，请提供专业代码级别的分析或建议，简洁易于理解。\n\n`;

  // Add specific instructions based on chat type
  switch (chatType) {
    case 1: // Debug/Error correction
      prompt +=
        "我需要你帮我找出代码中的错误，并给出修复建议。请详细说明错误原因和修复方案，如有类型错误，须使用jsdoc加上类型注释。";
      break;
    case 2: // Code optimization
      prompt +=
        "请帮我优化这段代码，提高执行效率、可读性和可维护性。可以从算法复杂度、代码结构、命名规范等多方面给出建议，如有类型错误，须使用jsdoc加上类型注释。";
      break;
    case 3: // Code explanation
      prompt +=
        "请详细解释这段代码的功能和实现原理，包括核心逻辑、算法思路和关键部分的具体作用。";
      break;
    case 6: // Comment generation
      prompt +=
        "请为这段代码添加全面的注释，使其更易于理解和维护。注释应包括函数用途、参数说明、返回值、实现逻辑等关键信息，如有类型错误，须使用jsdoc加上类型注释。";
      break;
    case 8: // API explanation
      prompt +=
        "请详细解释这段代码中使用的API，包括各API的功能、参数、返回值以及使用场景。如果可能，也请提供一些实用的示例代码。";
      break;
    case 13: // Function refactoring
      prompt +=
        "请帮我重构这个较长的函数，将其分解为多个小函数，提高代码的可读性和可维护性。保持原有功能不变，如有类型错误，须使用jsdoc加上类型注释。";
      break;
    case 14: // Code structure analysis
      prompt +=
        "请分析这段代码的结构，包括模块划分、函数间的依赖关系、数据流向等。如有可能，你可以建议更合理的结构组织方式。";
      break;
    case 90: // Error fix
      prompt +=
        "这是一段报错的代码，错误信息在双引号内。请帮我修复这个错误，并解释错误原因，如有类型错误，须使用jsdoc加上类型注释。";
      break;
    case 200: // Custom question
    default:
      prompt +=
        "我有一个关于这段代码的问题，请根据我的描述提供专业的解答和建议。";
      break;
  }

  return prompt;
}

/**
 * Fetches user information from the auth API
 * @param {string} authHeader - The authorization header
 * @returns {Promise} - Promise resolving to user information
 */
export function fetchUserInfo(authHeader) {
  return new Promise((resolve, reject) => {
    $.ajax("https://code-api-pc.dao3.fun/auth/user", {
      method: "get",
      headers: { Authorization: authHeader },
      success: (result) => {
        resolve(result);
      },
      error: (error) => {
        reject(error);
      },
    });
  });
}

/**
 * 获取当前操作类型的描述
 * @param {number} type - 操作类型ID
 * @returns {string} - 操作类型描述
 */
function getOperationTypeDescription(type) {
  switch (type) {
    case 1:
      return "纠正代码错误";
    case 2:
      return "优化代码结构";
    case 3:
      return "解释代码功能";
    case 6:
      return "添加代码注释";
    case 8:
      return "API功能详解";
    case 13:
      return "重构长函数";
    case 14:
      return "分析代码架构";
    case 90:
      return "修复错误提示";
    case 200:
      return "自定义问题";
    default:
      return "代码分析";
  }
}

/**
 * 格式化代码预览，确保代码高亮
 * @param {string} code - 要格式化的代码
 * @param {number} maxLength - 最大字符数
 * @returns {string} - 格式化后的HTML
 */
function formatCodePreview(code, maxLength = 300) {
  if (!code || code.trim().length === 0) return "";

  // 检测语言，简单检测，可以通过文件扩展名或内容特征来优化
  let language = detectLanguage(code);

  // 截断代码
  const isTruncated = code.length > maxLength;
  const displayCode = isTruncated ? code.substring(0, maxLength) + "..." : code;

  return `
    <div class="selected-code">
      <strong>选中的代码片段：</strong>
      <pre><code class="language-${language}">${escapeHtml(
    displayCode
  )}</code></pre>
      ${
        isTruncated
          ? '<div class="code-truncated">代码已截断显示，完整代码将用于分析</div>'
          : ""
      }
    </div>
  `;
}

/**
 * 根据代码内容检测编程语言
 * @param {string} code - 代码内容
 * @returns {string} - 检测到的语言
 */
function detectLanguage(code) {
  // 基本语言检测逻辑
  if (
    code.includes("import React") ||
    code.includes("useState") ||
    code.includes("extends React.Component")
  ) {
    return "jsx";
  } else if (
    code.includes("function") &&
    (code.includes("=>") || code.includes("return"))
  ) {
    return "javascript";
  } else if (
    code.includes("class") &&
    code.includes("extends") &&
    code.includes("public")
  ) {
    return "java";
  } else if (code.includes("def ") && code.includes(":")) {
    return "python";
  } else if (code.includes("#include")) {
    return "cpp";
  } else if (code.includes("<template>") && code.includes("<script>")) {
    return "vue";
  } else if (code.includes("<?php")) {
    return "php";
  } else if (code.includes("package") && code.includes("func")) {
    return "go";
  } else if (
    code.includes(".map(") ||
    code.includes("=>") ||
    code.includes("const ")
  ) {
    return "javascript";
  }

  // 默认返回javascript
  return "javascript";
}

/**
 * 转义HTML特殊字符
 * @param {string} text - 要转义的文本
 * @returns {string} - 转义后的文本
 */
function escapeHtml(text) {
  return text
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;");
}

/**
 * 自动滚动到内容底部，但不会频繁触发
 * @param {HTMLElement} element - 需要滚动的元素
 */
function smoothScrollToBottom(element) {
  if (!element) return;

  // 获取元素的滚动位置
  const isScrolledToBottom =
    element.scrollHeight - element.clientHeight <= element.scrollTop + 150;

  // 只有当滚动条距离底部超过一定距离时才滚动
  if (isScrolledToBottom) {
    element.scrollTop = element.scrollHeight;
  }
}

/**
 * Sets up the toggle functionality for reasoning content
 * @param {HTMLElement} reasoningElement - The reasoning container element
 * @param {boolean} autoCollapse - Whether to auto-collapse on completion
 */
function setupReasoningToggle(reasoningElement, autoCollapse = false) {
  if (!reasoningElement) return;

  const toggleButton = reasoningElement.querySelector(".ai-reasoning-toggle");
  if (!toggleButton) return;

  // Set initial state based on autoCollapse flag
  if (autoCollapse) {
    reasoningElement.classList.add("collapsed");
    toggleButton.classList.add("collapsed");
  } else {
    reasoningElement.classList.remove("collapsed");
    toggleButton.classList.remove("collapsed");
  }

  // Add click event
  toggleButton.addEventListener("click", () => {
    reasoningElement.classList.toggle("collapsed");
    toggleButton.classList.toggle("collapsed");
  });
}

/**
 * Sends a chat interaction to the AI service
 * @param {string} value - The code or question text
 * @param {number} type - The type of chat interaction
 * @param {string} customInput - Custom input text (optional)
 * @param {string} selectedCode - Selected code (optional)
 * @param {boolean} isAll - Whether to use all code (optional)
 * @param {Object} config - Configuration options
 * @returns {Promise} - Promise resolving when the chat is complete
 */
export async function sendChatRequest(
  value,
  type,
  customInput = "",
  selectedCode = "",
  isAll = false,
  config
) {
  try {
    // Prepare chat request data
    const chat_value = value;
    const modelId = isAll
      ? "allcode"
      : document.getElementById("selectBox").value;

    // Get elements
    const gptelement = document.getElementById("chat");
    const aiDiv2 = document.getElementById("aiDiv2");
    const aiDivMain = document.getElementById("aiDivMain");

    // 构建用户提问部分
    let userQuestionText = customInput || getOperationTypeDescription(type);
    const userQuestion = `<div class="user-question">${userQuestionText}</div>`;

    // 格式化选中的代码
    const codePreview = selectedCode ? formatCodePreview(selectedCode) : "";

    // 组合用户问题和代码预览
    const userContent = userQuestion + codePreview;

    // 设置初始加载界面
    gptelement.innerHTML =
      userContent +
      `
      <div class="ai-response">
       
        <div class="ai-thinking">
          <div class="dot-typing"></div>
          <div class="thinking-text">正在思考分析中...</div>
        </div>
      </div>
    `;

    // 创建一个容器元素来保存动态更新的内容
    const contentContainer = document.createElement("div");
    contentContainer.className = "ai-content";

    try {
      // Make the API request
      const resp = await fetch(
        "https://api.fastgpt.in/api/v1/chat/completions",
        {
          method: "POST",
          headers: {
            Authorization:
              "Bearer fastgpt-fZBtJyNzBGO42dWcvTa7moMHNHiGuUgEpeFnshrfzM2YkyFGmuscevg3FDCWSAo",
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            chatId: modelId,
            stream: true,
            variables: {
              auth: config.authHeader,
              ua: navigator.userAgent,
              languageType: "JavaScript",
            },
            messages: [
              {
                role: "system",
                content: generatePrompt({
                  chatType: type,
                  languageType: "JavaScript",
                }),
              },
              {
                content: chat_value,
                role: "user",
              },
            ],
          }),
        }
      );

      if (!resp.ok) {
        throw new Error(`API请求失败: HTTP状态 ${resp.status}`);
      }

      let dlgtext = "";
      let rdlgtext = "";
      let lastUpdateTime = Date.now();
      let hasReasoningContent = false;

      // 定期更新DOM，而不是每次数据到达就更新
      let pendingUpdate = false;

      // 设置响应结构，只设置一次，避免重复渲染
      gptelement.innerHTML =
        userContent +
        `
        <div class="ai-response">
        
          <div class="ai-content"></div>
        </div>
      `;

      // 获取ai-content元素的引用，后续只更新这个元素的内容
      const aiContentElement = gptelement.querySelector(".ai-content");

      const reader = resp.body.getReader();
      const decoder = new TextDecoder();

      while (true) {
        const { done, value } = await reader.read();
        if (done) {
          // 最终更新内容
          const reasoningHtml = rdlgtext
            ? `<div class="ai-reasoning">
                <div class="ai-reasoning-header">
                  <div class="ai-reasoning-icon"></div>
                  AI思考过程
                  <div class="ai-reasoning-toggle"></div>
                </div>
                <div class="ai-reasoning-content">${marked.parse(
                  rdlgtext
                )}</div>
              </div>`
            : "";

          aiContentElement.innerHTML = reasoningHtml + marked.parse(dlgtext);

          // 添加思考过程的折叠/展开功能
          if (rdlgtext) {
            const reasoningElement =
              aiContentElement.querySelector(".ai-reasoning");
            setupReasoningToggle(reasoningElement, true);
          }

          // 应用代码高亮
          hljs.highlightAll();

          // 添加代码操作按钮
          updateChatContent(dlgtext);

          // Record chat log if not processing all code
          if (!isAll) {
            try {
              await $.ajax("https://api.box3lab.com/v1/chat_completionslog", {
                method: "POST",
                data: JSON.stringify({
                  uid: config.userId,
                  time: Math.floor(Date.now() / 1000),
                  dlgtext: dlgtext,
                  chat: chat_value,
                }),
                contentType: "application/json",
                headers: { "Content-Type": "application/json;charset=UTF-8" },
              });
            } catch (logError) {
              console.error("Failed to log chat:", logError);
              // Non-critical error, don't affect user experience
            }
          }
          break;
        }

        const txt = decoder.decode(value);
        const dataParts = txt.split("data: ");

        dataParts.forEach((part, index) => {
          if (index === 0) return;
          try {
            const data = JSON.parse(part.trim());

            // 处理思考内容
            const reasoningContent = data.choices[0].delta.reasoning_content;
            if (reasoningContent) {
              rdlgtext += reasoningContent;
              hasReasoningContent = true;
            }

            // 处理回复内容
            dlgtext += data.choices[0].delta.content ?? "";

            // 避免频繁更新DOM，使用节流方法
            const now = Date.now();
            if (now - lastUpdateTime > 150 && !pendingUpdate) {
              // 每150ms更新一次
              pendingUpdate = true;

              // 使用requestAnimationFrame以避免在渲染周期中间更新
              requestAnimationFrame(() => {
                // 如果有思考内容，添加思考区域
                let content = "";

                if (hasReasoningContent) {
                  content = `<div class="ai-reasoning">
                    <div class="ai-reasoning-header">
                      <div class="ai-reasoning-icon"></div>
                      AI思考过程
                      <div class="ai-reasoning-toggle"></div>
                    </div>
                    <div class="ai-reasoning-content">${marked.parse(
                      rdlgtext
                    )}</div>
                  </div>`;
                }

                // 更新内容
                aiContentElement.innerHTML = content + marked.parse(dlgtext);

                // 如果有思考内容，添加展开/折叠功能
                if (hasReasoningContent) {
                  const reasoningElement =
                    aiContentElement.querySelector(".ai-reasoning");
                  setupReasoningToggle(reasoningElement, false);
                }

                // 应用代码高亮
                hljs.highlightAll();

                // 智能滚动
                scrollToTop(document.getElementById("aiDivMain"));

                lastUpdateTime = Date.now();
                pendingUpdate = false;
              });
            }
          } catch (error) {
            // 解析错误，但不中断流
            console.warn("Stream parse error:", error);
          }
        });
      }

      return dlgtext;
    } catch (error) {
      // 处理API请求错误
      console.error("API请求错误:", error);
      gptelement.innerHTML =
        userContent +
        `
        <div class="ai-response">
        
          <div class="ai-error">
            <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="color: #ff6b6b;"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>
            抱歉，请求出错：${error.message}
            <button class="retry-button">重试</button>
          </div>
        </div>
      `;

      // Add retry functionality
      const retryButton = gptelement.querySelector(".retry-button");
      if (retryButton) {
        retryButton.addEventListener("click", () => {
          sendChatRequest(
            value,
            type,
            customInput,
            selectedCode,
            isAll,
            config
          );
        });
      }

      throw error;
    }
  } catch (e) {
    console.error("Chat request error:", e);
    throw e;
  }
}
